package aframe.http.net;

import java.io.File;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import aframe.http.Http;
import aframe.http.bean.HttpCookie;
import aframe.http.bean.HttpHeader;
import aframe.http.bean.HttpParam;
import aframe.http.bean.HttpTask;
import aframe.http.bean.URLEncoderStr;
import aframe.utils.LogUtils;
import aframe.utils.StringUtils;



public class DealHttp {

	private String charset = Http.CHARSET_UTF_8;

	public DealHttp() {

	}

	public DealHttp(String charset) {
		if(StringUtils.isNotBlank(charset)){
			this.charset = charset;
		}
	}

	public HttpTask request(HttpTask task) throws Exception {

		// 创建HttpClient
//		DefaultHttpClient client = new DefaultHttpClient();
		DefaultHttpClient client = getNewHttpClient();
		// 创建HttpUriRequest
		HttpUriRequest request = null;
		int method = task.getMethod();
		//
		log("请求方式:" + (method == Http.GET ? "GET" : "POST"));

		if (method == Http.GET) {
			request = requestForGet(task);
		} else if (method == Http.POST) {
			request = requestForPost(task);
		} else {
			throw new RuntimeException("请检查请求方式");
		}

		// 设置cookie
		if (task.hasHttpCookie()) {
			HttpCookie cookie = task.getHttpCookie();
			CookieStore cookieStore = client.getCookieStore();
			for (int i = 0; i < cookie.size(); i++) {
				log("请求cookie信息:" + cookie.getKey(i) + "=" + cookie.getValue(i));
				cookieStore.addCookie(new BasicClientCookie(cookie.getKey(i), cookie.getValue(i)));
			}
			client.setCookieStore(cookieStore);
		}

		// 设置头信息
		if (task.hasHttpHeader()) {
			HttpHeader header = task.getHttpHeader();
			for (int i = 0; i < header.size(); i++) {
				log("请求头信息:" + header.getKey(i) + "=" + header.getValue(i));
				request.setHeader(header.getKey(i), header.getValue(i));
			}
		}
		// 执行
		HttpResponse response = client.execute(request);

		// 查看所有返回头部信息
		Header headers[] = response.getAllHeaders();
		HttpHeader header = new HttpHeader();
		for (int i = 0; i < headers.length; i++) {
			log("返回头信息:" + headers[i].getName() + "=" + headers[i].getValue());
			header.add(headers[i].getName(), headers[i].getValue());
		}
		task.setHttpHeader(header);

		// 设置返回的cookie
		CookieStore cookieStore = client.getCookieStore();
		HttpCookie httpCookie = new HttpCookie();
		List<Cookie> cookies = cookieStore.getCookies();
		for (Cookie cookie : cookies) {
			log("返回Cookie:" + cookie.getName() + "=" + cookie.getValue());
			httpCookie.add(cookie.getName(), cookie.getValue());
		}
		task.setHttpCookie(httpCookie);

		int statusCode = response.getStatusLine().getStatusCode();
		task.setResponseCode(statusCode);
		log("状态码:" + statusCode);
		String data = EntityUtils.toString(response.getEntity(),charset);
		task.setData(data);
		log("返回值:" + data);
		return task;
	}

	private HttpUriRequest requestForGet(HttpTask task) {
		String url = task.getUrl() + task.paramForGet();
		log("请求url:" + url);
		return new HttpGet(url);
	}

	private HttpUriRequest requestForPost(HttpTask task) throws Exception {
		HttpParam param = task.getParam();
		HttpEntity entity = null;
		String url = task.getUrl();
		log("请求url:" + url);
		if (task.isMultipart()) {
			MultipartEntity multipartEntity = new MultipartEntity();
			for (int i = 0; i < param.size(); i++) {
				String key = param.getKey(i);
				Object value = param.getValue(i);
				String className = value.getClass().getName();

				log("请求参数:" + key + "=" + String.valueOf(value));

				if (className.equals(Http.CLASSNAME_STRING)) {
					multipartEntity.addPart(key, new StringBody(new String(((String) value).getBytes(), this.charset), Charset.forName(this.charset)));
				} else if (className.equals(Http.CLASSNAME_FILE)) {
					multipartEntity.addPart(key, new FileBody((File) value));
				} else if (className.equals(Http.CLASSNAME_URLENCODE_STRING)) {
					multipartEntity.addPart(key, new StringBody(new String(((URLEncoderStr) value).getStr().getBytes(), this.charset), Charset.forName(this.charset)));
				} else {
					multipartEntity.addPart(key, new StringBody(String.valueOf(value)));
				}

			}
			entity = multipartEntity;
		} else {
			List<BasicNameValuePair> formParams = new ArrayList<BasicNameValuePair>();
			for (int i = 0; i < param.size(); i++) {
				String key = param.getKey(i);
				Object value = param.getValue(i);
				String className = value.getClass().getName();

				log("请求参数:" + key + "=" + String.valueOf(value));

				if (className.equals(Http.CLASSNAME_STRING)) {
					formParams.add(new BasicNameValuePair(key, new String(((String) value).getBytes(), this.charset)));
				} else {
					formParams.add(new BasicNameValuePair(key, String.valueOf(value)));
				}
			}

			entity = new UrlEncodedFormEntity(formParams, this.charset);
		}

		HttpPost post = new HttpPost(url);
		post.setEntity(entity);
		return post;
	}

	private void log(String msg) {
		LogUtils.log(msg);
	}
	
	public DefaultHttpClient getNewHttpClient() {
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			trustStore.load(null, null);

			SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
			sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

			HttpParams params = new BasicHttpParams();
			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

			SchemeRegistry registry = new SchemeRegistry();
			registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
			registry.register(new Scheme("https", sf, 443));

			ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

			return new DefaultHttpClient(ccm, params);
		} catch (Exception e) {
			return new DefaultHttpClient();
		}
	}
}
